package com.fjzx.androidframe.ui.xrecyclerview;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.fjzx.androidframe.ui.R;


public class XRecyclerView extends LinearLayout {
    private RecyclerView rvList;
    private SwipeRefreshLayout srRefresh;
    private View llLoadMore;
    private TextView loadMoreText;
    private View llEmpty;
    private View llError;
    private View btErrorRetry;
    private TextView tvError;
    private TextView tvEmpty;

    private PullLoadMoreListener listener;
    private boolean hasMore = true;
    private boolean isLoadMore = false;
    private boolean pullRefreshEnable = true;
    private boolean pushRefreshEnable = true;
    private FooterItemDecoration footerDecoration;

    public XRecyclerView(Context context) {
        super(context);
        initView(context);
    }

    public XRecyclerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView(context);
    }

    private void initView(Context context) {
        LayoutInflater.from(context).inflate(R.layout.base_layout_xrecyclerview, this);
        srRefresh = findViewById(R.id.sr_refresh);
        rvList = findViewById(R.id.rv_recyclerview);
        llLoadMore = findViewById(R.id.ll_loadmore);
        loadMoreText = findViewById(R.id.tv_loadmore);
        llEmpty = findViewById(R.id.ll_empty);
        llError = findViewById(R.id.ll_error);
        btErrorRetry = findViewById(R.id.bt_retry);
        tvError = findViewById(R.id.tv_error);
        tvEmpty = findViewById(R.id.tv_empty);

        srRefresh.setColorSchemeResources(R.color.colorPrimary);
        footerDecoration = new FooterItemDecoration();
        rvList.addItemDecoration(footerDecoration);
        rvList.setItemAnimator(new DefaultItemAnimator());
        rvList.addOnScrollListener(new RecyclerViewOnScroll(this));
        rvList.setOnTouchListener(new onTouchRecyclerView());
        srRefresh.setOnRefreshListener(new SwipeRefreshLayoutOnRefresh(this));
        btErrorRetry.setOnClickListener(v -> {
            setRefreshing(true);
            refresh();
        });
    }

    public void setAdapter(RecyclerView.Adapter adapter) {
        rvList.setAdapter(adapter);
        adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
            @Override
            public void onChanged() {
                loadMoreCompleted();
            }

            @Override
            public void onItemRangeChanged(int positionStart, int itemCount) {
                if (itemCount > 0) {
                    loadMoreCompleted();
                }
            }

            @Override
            public void onItemRangeChanged(int positionStart, int itemCount, @Nullable Object payload) {
                if (itemCount > 0) {
                    loadMoreCompleted();
                }
            }

            @Override
            public void onItemRangeInserted(int positionStart, int itemCount) {
                if (itemCount > 0) { loadMoreCompleted(); }
            }

            @Override
            public void onItemRangeRemoved(int positionStart, int itemCount) {
                if (itemCount > 0) { loadMoreCompleted(); }
            }

            @Override
            public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
                if (itemCount > 0) { loadMoreCompleted(); }
            }
        });
    }

    public void linearVertical(RecyclerView.Adapter adapter, PullLoadMoreListener listener) {
        setLayoutManager(new LinearLayoutManager(getContext()));
        setAdapter(adapter);
        setOnPullLoadMoreListener(listener);
    }

    public void setLayoutManager(RecyclerView.LayoutManager manager) {
        rvList.setLayoutManager(manager);
    }

    public RecyclerView.LayoutManager getLayoutManager() {
        return rvList.getLayoutManager();
    }

    public RecyclerView getRecyclerView() {
        return rvList;
    }

    public void setItemAnimator(RecyclerView.ItemAnimator animator) {
        rvList.setItemAnimator(animator);
    }

    public void addItemDecoration(RecyclerView.ItemDecoration decor, int index) {
        rvList.addItemDecoration(decor, index);
    }

    public void addItemDecoration(RecyclerView.ItemDecoration decor) {
        rvList.addItemDecoration(decor);
    }

    public void scrollToTop() {
        rvList.scrollToPosition(0);
    }

    public void setPullRefreshEnable(boolean enable) {
        pullRefreshEnable = enable;
        setSwipeRefreshEnable(enable);
    }

    public boolean getPullRefreshEnable() {
        return pullRefreshEnable;
    }

    public void setSwipeRefreshEnable(boolean enable) {
        srRefresh.setEnabled(enable);
    }

    public boolean getSwipeRefreshEnable() {
        return srRefresh.isEnabled();
    }

    public void setColorSchemeResources(int... colorResIds) {
        srRefresh.setColorSchemeResources(colorResIds);
    }

    public SwipeRefreshLayout getSwipeRefreshLayout() {
        return srRefresh;
    }

    public void setRefreshing(boolean isRefreshing) {
        srRefresh.postDelayed(() -> {
            if (pullRefreshEnable) {
                srRefresh.setRefreshing(isRefreshing);
            }
        }, 100);
    }

    public class onTouchRecyclerView implements OnTouchListener {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            return srRefresh.isRefreshing() || isLoadMore;
        }
    }

    public boolean getPushRefreshEnable() {
        return pushRefreshEnable;
    }

    public void setPushRefreshEnable(boolean pushRefreshEnable) {
        this.pushRefreshEnable = pushRefreshEnable;
    }

    public View getLoadMoreView() {
        return llLoadMore;
    }

    public void setLoadMoreViewBackgroundColor(int color) {
        llLoadMore.setBackgroundColor(ContextCompat.getColor(getContext(), color));
    }

    public void setFooterViewText(CharSequence text) {
        loadMoreText.setText(text);
    }

    public void setFooterViewText(int resid) {
        loadMoreText.setText(resid);
    }

    public void setFooterViewTextColor(int color) {
        loadMoreText.setTextColor(ContextCompat.getColor(getContext(), color));
    }

    public void refresh() {
        if (listener != null) {
            listener.onRefresh();
        }
        hasMore = true;
        showContent();
    }

    public void loadMore() {
        if (listener != null && hasMore) {
            llLoadMore.animate()
                    .translationY(0)
                    .setDuration(200)
                    .setInterpolator(new AccelerateDecelerateInterpolator())
                    .setListener(new AnimatorListenerAdapter() {
                        @Override
                        public void onAnimationStart(Animator animation) {
                            llLoadMore.setVisibility(View.VISIBLE);
                        }
                    })
                    .start();
            invalidate();
            listener.onLoadMore();
        }
    }

    public void loadMoreCompleted() {
        isLoadMore = false;
        llLoadMore.animate()
                .translationY(llLoadMore.getHeight())
                .setDuration(300)
                .setInterpolator(new AccelerateDecelerateInterpolator())
                .start();
        if (rvList.getAdapter() != null && rvList.getAdapter().getItemCount() > 0) {
            rvList.setVisibility(VISIBLE);
            llEmpty.setVisibility(GONE);
            llError.setVisibility(GONE);
            rvList.invalidateItemDecorations();
        }
    }

    public void setOnPullLoadMoreListener(PullLoadMoreListener listener) {
        this.listener = listener;
    }

    public boolean isLoadMore() {
        return isLoadMore;
    }

    public void setIsLoadMore(boolean isLoadMore) {
        this.isLoadMore = isLoadMore;
    }

    public boolean isHasMore() {
        return hasMore;
    }

    public void setHasMore(boolean hasMore) {
        footerDecoration.setDrawFooter(!hasMore);
        this.hasMore = hasMore;
        loadMoreCompleted();
        rvList.invalidateItemDecorations();
    }

    public boolean isRefreshing() {
        return srRefresh.isRefreshing();
    }

    public interface PullLoadMoreListener {
        void onRefresh();

        void onLoadMore();
    }

    public abstract static class SimplePullLoadMoreListener implements PullLoadMoreListener{
        @Override
        public void onLoadMore() { }
    }

    private void showContent() {
        rvList.setVisibility(VISIBLE);
        llError.setVisibility(GONE);
        llEmpty.setVisibility(GONE);
    }

    public void showEmpty() {
        setRefreshing(false);
        rvList.setVisibility(GONE);
        llError.setVisibility(GONE);
        llEmpty.setVisibility(VISIBLE);
    }

    public void showError() {
        setRefreshing(false);
        rvList.setVisibility(GONE);
        llError.setVisibility(VISIBLE);
        llEmpty.setVisibility(GONE);
    }

    public void showEmpty(String msg) {
        showEmpty();
        tvEmpty.setText(msg);
    }

    public void showError(String msg) {
        showError();
        tvError.setText(msg);
    }
}
